home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
MAIN.C
< prev
next >
Wrap
Text File
|
1993-10-18
|
34KB
|
1,502 lines
/* Main network program - provides both client and server functions */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <alloc.h>
#include <time.h>
#include "global.h"
#include <fcntl.h>
#include <dos.h>
#include <io.h>
#include <conio.h>
#include <ctype.h>
#include <dir.h>
#include <sys\stat.h>
#include "config.h"
#ifdef ANSIPROTO
#include <stdarg.h>
#endif
#include "files.h"
#include "mbuf.h"
#include "socket.h"
#include "iface.h"
#include "devparam.h"
#include "ftp.h"
#include "telnet.h"
#include "remote.h"
#include "session.h"
#include "cmdparse.h"
#include "ax25.h"
#include "arp.h"
#include "kiss.h"
#include "enet.h"
#include "timer.h"
#include "proc.h"
#include "tty.h"
#include "daemon.h"
#include "domain.h"
#include "usock.h"
#include "netrom.h"
#include "ip.h"
#include "tcp.h"
#ifdef UDP
#include "udp.h"
#endif
#include "hardware.h"
#include "commands.h"
#include "asy.h"
#include "slip.h"
#include "trace.h"
#ifdef SCC
#include "scc.h"
#endif
#ifdef VANESSA
#include "vanessa.h"
#endif
#include "event.h"
unsigned int _stklen = 8192;
static char Escape = 0x1b; /* default escape character is ESC */
char Badhost[] = "Unknown host %s\n";
char Invcall[] = "Invalid call %s\n";
char Hostname[30];
static int Logging = FALSE;
static int Logwait = 0;
static struct proc *Cmdpp, *statp;
struct proc *Display;
struct session *Command, *Trace;
static time_t StartTime; /* Time that NOS was started */
int32 currtime = 0;
char uploadstatus = 1;
int Niface = 0; /* Number of Ifaces */
#ifdef LZW
int16 Lzwbits = LZWBITS;
int Lzwmode = LZWCOMPACT;
#endif
static void near loadfile __ARGS((void));
static char version[] = "\nKA9Q NOS based %s (%s)\n"
"Copyright 1993 by Phil Karn (KA9Q), "
"WAMPES parts by DK5SG, and others.\n\n";
#define NORMALL 48
#define NORMALH 23
#define NORMALS 113
#define INVERS 30
#define RED 71
#define COMMON 7
#define PANIC 206
static int normal = NORMALL; /* used for statusline */
static int normalh = NORMALH;
static int normals = NORMALS;
static int invers = INVERS;
static int red = RED;
static int common = COMMON;
static int panic = PANIC;
static void dostatustimer __ARGS((void));
struct timer Statustimer;
static unsigned char Currmode;
#undef RESETTIMER
#ifdef RESETTIMER
/* Timer card - developed by DL3YDN.9203xx
* code is compiled in when defining RESETTIMER
*
* Register des Timers 8253
*/
#define TIMCTRL 0x213
#define TIMER0 0x210
#define TIMER1 0x211
#define TIMER2 0x212
/* Register des I/O Bausteins 8255 */
#define IOCTRL 0x217
#define PORTA 0x214
#define PORTB 0x215
#define PORTC 0x216
static void near inittim __ARGS((void));
#endif
unsigned char Nrows = NROWS; /* extra defined for 43/50 line mode - DB3FL */
int
main(int argc,char **argv)
{
struct daemon *tp;
struct mbuf *bp;
int c, i;
char *startfile[3], root[MAXPATH];
struct time sttime;
struct text_info r;
delay(0);
randomize();
gettextinfo(&r);
Currmode = r.currmode;
directvideo = 1;
*root = '\0';
do {
optarg = NULLCHAR;
c = getopt(argc,argv,"s:d:be");
switch(c){
case 's': /* Number of sockets */
Nusock = atoi(optarg);
break;
case 'd': /* Root directory for various files */
strcpy(root,optarg);
break;
#ifdef __TURBOC__
case 'b': /* Use BIOS for screen output */
directvideo = 0;
break;
#endif
#ifdef __CPLUSPLUS
case 'e':
textmode(C4350);
gettextinfo(&r);
break;
#endif
case '?':
printf("aborted...\007\r\n");
exit(1);
}
} while (c != EOF);
initroot(root);
Nrows = r.screenheight;
#ifdef RESETTIMER
inittim();
#endif
if(getenv("TZ") == NULL) {
putenv("TZ=UTC-1");
}
tzset();
currtime = StartTime = time(&StartTime);
gettime(&sttime);
EMinute = sttime.ti_hour * 60 + sttime.ti_min;
ioinit();
kinit();
sockinit();
Cmdpp = mainproc("cmdintrp");
window(1,3,80,Nrows);
/*-------------------------------------------------------------------*
* initialize name cache DK5DC *
*--------------------------------------------------------------------*/
cache = cxallocw(sizeof(Cache),(Dcache_size + 2));
Sessions = cxallocw(Nsessions,sizeof(struct session));
Trace = newsession("Trace",TRACESESSION,SPLIT);
Lastcurr = Command = newsession("cmd interpreter",COMMAND,SWAP);
Command->flowmode = Cooked; /* set 'more' paging on command screen */
Trace->input = Command->input;
Display = newproc("display",512,display,0,NULLCHAR,NULL,0);
/* Start background Daemons */
for(tp = Daemons; tp->name != NULLCHAR; tp++) {
newproc(tp->name,tp->stksize,tp->fp,0,NULLCHAR,NULL,0);
for(i = 0; i < 1000; i++) ;
}
/* allocates buffer for the trace screen */
swapscreen(Trace,NULLSESSION);
tprintf(version,Version,__DATE__);
*Hostname = '\0';
startfile[1] = strxdup(optind < argc ? argv[optind] : Startup);
dosource(1,startfile,NULL);
xfree(startfile[1]);
if(Niface) {
loadfile();
}
uploadstatus = 0;
Command->flag = 1;
/* Now loop forever, processing commands */
for(;;){
if(Current == Command && Command->flag) { /* DK5DC */
if(*Hostname) {
tprintf("%s> ",Hostname);
} else {
tputs("net> ");
}
Command->flag = 0;
tflush();
}
pwait(NULL);
if(recv_mbuf(Command->input,&bp,0,NULLCHAR,0) != -1){
cmdparse(Cmds,bp->data,Lastcurr);
free_p(bp);
}
}
}
/* Keyboard input process */
void
keyboard(int i,void *v1,void *v2)
{
int c, j, k;
struct mbuf *bp;
struct session *sp;
/* Keyboard process loop */
for(;;) {
if((c = kbread()) == Escape && Escape != 0) {
c = -2;
}
if(c == -2 && Current != Command) {
/* Save current tty mode and set cooked */
swapscreen(Current,Command);
Lastcurr = Current;
Current = Command;
if(Command->flag) {
if(*Hostname) {
tprintf("%s> ",Hostname);
} else {
tputs("net> ");
}
Command->flag = 0;
tflush();
}
/* set 'more' paging on command screen */
Command->flowmode = Cooked;
}
if(c < -2) { /* F1 to F10 pressed */
if(c == -13) { /* F9 handled here */
if(Current != Trace) {
swapscreen(Current,Trace);
Lastcurr = Current;
Current = Trace;
Trace->flowmode = Raw;
} else {
swapscreen(Trace,Lastcurr);
Current = Lastcurr;
Lastcurr = Trace;
}
} else {
for(sp = Sessions, j = 1, k = abs(c); sp < &Sessions[Nsessions]; sp++) {
if(sp->type != COMMAND) {
j++;
if(sp->type != FREE && j == k) {
swapscreen(Current,sp);
Lastcurr = Current;
Current = sp;
break;
}
}
}
}
}
Current->row = (Current->split) ? Nrows - 5 : Nrows - 3;
psignal(&Current->row,1);
if(c >= 0) {
/* If the screen driver was in morewait state, this char
* has woken him up. Toss it so it doesn't also get taken
* as normal input. If the char was a command escape,
* however, it will be accepted; this gives the user
* a way out of lengthy output.
*/
if(!Current->morewait) {
if((bp = ttydriv(Current,c)) == NULLBUF){
if(Current->lwrap >= 30
&& len_p(Current->ttystate.line) > Current->lwrap
&& Command != Current
&& (c == 32 || c == '-')) {
bp = ttydriv(Current,13);
send_mbuf(Current->input,bp,0,NULLCHAR,0);
}
} else {
send_mbuf(Current->input,bp,0,NULLCHAR,0);
}
}
}
}
}
/* Standard commands called from main */
/* exit cmd now give the value of argv[1] as the errorlevel to DOS.
* values greater than 255 are cut to a maximum of 255.
*/
int
doexit(int argc,char **argv,void *p)
{
int arg = atoi(argv[1]);
#ifdef RESETTIMER
outport(PORTC,0x00); /* Disable Watchdog */
#endif
uploadstatus = 1;
while(arg > 256) {
arg -= 256;
}
if(arg < 250) {
int i;
reset_all();
shuttrace();
for(i = 0; i < 100; i++) {
pwait(NULL);
}
}
log(-1,9983,"Shutdown %s Exit code %d",ctime(&currtime),arg);
iostop();
/* restore video mode */
textmode(Currmode);
exit(arg);
return 0; /* To satisfy lint */
}
int
dohostname(int argc,char **argv,void *p)
{
if(argc < 2) {
tprintf("%s\n",Hostname);
} else {
sprintf(Hostname,"%.27s",argv[1]);
}
return 0;
}
int
dolog(int argc,char **argv,void *p)
{
int OldLogging = Logging;
setbool(&Logging,"Logging",argc,argv);
if(OldLogging == FALSE && Logging == TRUE) {
log(-1,9983,"Startup %s",ctime(&StartTime));
}
return 0;
}
int
dohelp(int argc,char **argv,void *p)
{
if(argc < 2) {
int i;
struct cmds *cmdp;
tputs("Main commands:\n");
for(i = 0, cmdp = Cmds; cmdp->name != NULLCHAR; cmdp++) {
if(strlen(cmdp->name) > 0) {
tprintf("%-15.15s%s",cmdp->name,(i == 4) ? "\n" : "");
i = (i + 1) % 5;
}
}
if(i) {
tputs("\n");
}
} else {
gethelp(9983,Curproc->output,argv[1]);
}
return 0;
}
/* Manipulate I/O device parameters */
int
doparam(int argc,char **argv,void *p)
{
int param, set;
struct iface *ifp;
int32 val = -1;
if((ifp = if_lookup(argv[1])) == NULLIF) {
tprintf(Badif,argv[1]);
return -1;
}
if(ifp->ioctl != 0) {
if(argc < 3) {
for(param = 1; param <= 16; param++) {
if((val = (*ifp->ioctl)(ifp,param,FALSE,0)) != -1)
tprintf("%s: %ld\n",parmname(param),val);
}
return 0;
}
if((param = devparam(argv[2])) == -1) {
tprintf("Unknown parameter %s\n",argv[2]);
return -1;
}
if(param == PARAM_STRING) {
struct mbuf *hbp;
int i;
char *cp;
/* Allocate space for arg bytes */
argc -= 3;
argv += 3;
hbp = alloc_mbuf(argc);
hbp->cnt = argc;
hbp->next = NULLBUF;
for(i = 0, cp = hbp->data; i < argc; ) {
*cp++ = atoi(argv[i++]);
}
if((int)hbp->data[0] != PARAM_RETURN) {
hbp->data[0] |= (ifp->port << 4);
}
if(ifp->port) {
ifp->rawsndcnt++;
ifp->lastsent = secclock();
}
/* Even more "raw" than kiss_raw */
slip_raw(Slip[ifp->xdev].iface,hbp);
return 0;
}
if(argc < 4) {
set = FALSE;
val = 0L;
} else {
set = TRUE;
val = atol(argv[3]);
}
}
if(val == -1 || (val = (*ifp->ioctl)(ifp,param,set,val)) < 0) {
tputs("Not supported\n");
} else if(set == FALSE) {
tprintf("%s: %ld\n",parmname(param),val);
}
return (int)val;
}
#ifdef AX25
/* Display or set IP interface control flags */
int
domode(int argc,char **argv,void *p)
{
struct arp_tab *arp;
int32 addr;
if((addr = resolve(argv[1])) == 0 || (arp = arp_lookup(ARP_AX25,addr)) == NULLARP) {
tprintf(Badhost,argv[1]);
return -1;
}
if(argc < 3) {
char *e = "", buf1[AXBUF];
switch(arp->flags) {
case DATAGRAM_MODE:
e = "Datagram";
break;
case CONNECT_MODE:
e = "VC";
break;
case IPCAM_MODE:
e = "IPCAM";
break;
default:
e = "unknown";
return 0;
}
tprintf("%s (%s): Mode %s\n",
strupr(argv[1]),pax25(buf1,arp->hw_addr),e);
return 0;
} else {
struct arp_tab *ap;
switch(argv[2][0]){
case 'd':
arp->flags = DATAGRAM_MODE;
break;
case 'v':
case 'c':
arp->flags = CONNECT_MODE;
break;
case 'i':
arp->flags = IPCAM_MODE;
break;
default:
tputs("Usage: mode <datagram|vc|ipcam>\n");
return -1;
}
for(ap = Arp_tab; ap != NULLARP; ap = ap->next) {
if(strcmp(arp->hw_addr,ap->hw_addr) == 0) {
ap->flags = arp->flags;
}
}
}
return 0;
}
#endif
int
doescape(int argc,char **argv,void *p)
{
if(argc < 2){
tprintf("Escape char: CTRL-%c\n",Escape + 'A' - 1);
return 0;
}
if(iscntrl(*argv[1])) {
Escape = *argv[1];
}
return 0;
}
#ifdef UDP
/* Generate system command packet. Synopsis:
* remote [-p port#] [-k key] [-a hostname] <hostname> reset|exit|kickme
*/
int
doremote(int argc,char **argv,void *p)
{
struct sockaddr_in fsock;
int s, c, klen;
char *data = NULLCHAR, *cmd, *host, x, *key = NULLCHAR;
int16 len = 1;
int32 addr = 0;
int16 port = IPPORT_REMOTE; /* Set default */
optind = 1; /* reinit getopt() */
while((c = getopt(argc,argv,"a:p:k:s:")) != EOF){
switch(c){
case 'a':
if((addr = resolve(optarg)) == 0){
tprintf(Badhost,optarg);
return -1;
}
break;
case 'p':
port = atoi(optarg);
break;
case 'k':
key = strxdup(optarg);
klen = strlen(key);
break;
case 's':
Rempass = strxdup(optarg);
return 0; /* Only set local password */
}
}
if(optind > argc - 2){
tputs("Insufficient args\n");
goto quit;
}
host = argv[optind++];
cmd = argv[optind];
if((s = socket(AF_INET,SOCK_DGRAM,0)) == -1){
tputs(Nosocket);
goto quit;
}
/* Did the user include a password or kickme target? */
if(addr != 0 && cmd[0] == 'k')
len += sizeof(int32);
if(key != NULLCHAR && (cmd[0] == 'r' || cmd[0] == 'e'))
len += klen;
if(len == 1) {
data = &x;
} else {
data = mxallocw(len);
}
fsock.sin_family = AF_INET;
if((fsock.sin_addr.s_addr = resolve(host)) == 0){
tprintf(Badhost,host);
goto cleanup;
}
fsock.sin_port = port;
switch(*cmd){
case 'r':
data[0] = SYS_RESET;
if(key != NULLCHAR)
sprintf(&data[1],"%.*s",klen,key);
break;
case 'e':
data[0] = SYS_EXIT;
if(key != NULLCHAR)
sprintf(&data[1],".*s",klen,key);
break;
case 'k':
data[0] = KICK_ME;
if(addr != 0)
put32(&data[1],addr);
break;
default:
tprintf("Unknown command %s\n",cmd);
goto cleanup;
}
/* Form the command packet and send it */
if(sendto(s,data,len,0,(char *)&fsock,SOCKSIZE) == -1) {
tprintf("sendto failed: %s\n",sys_errlist[errno]);
}
cleanup:
close_s(s);
quit:
if(data != &x)
xfree(data);
if(key != NULLCHAR)
xfree(key);
return 0;
}
#endif
int
domore(int argc,char **argv,void *p)
{
struct session *sp;
FILE *fp;
char buf[LINELEN];
int row = Nrows - 3;
if((fp = Fopen(argv[1],READ_TEXT,0,1)) == NULLFILE) {
return -1;
}
if((sp = newsession(argv[1],MORE,SWAP)) == NULLSESSION) {
Fclose(fp);
tputs(Nosess);
return -1;
}
/* Put tty into raw mode so single-char responses will work */
sp->ttystate.echo = sp->ttystate.edit = 0;
while(fgets(buf,LINELEN,fp) != NULL){
tputs(buf);
if(--row == 0){
row = keywait("--More--",0);
switch(row){
case -1:
case 'q':
case 'Q':
goto done;
case '\n':
case '\r':
row = 1;
break;
/* case ' ': */
default:
row = Nrows - 3;
}
}
}
done:
Fclose(fp);
keywait(NULLCHAR,1);
freesession(sp);
return 0;
}
int
dotail(int argc,char **argv,void *p)
{
int handle, i;
unsigned line = 0, rdsize = 2000;
long length;
char buffer[2000];
static char Noread[] = "Can't read %s: %s\n";
if((handle = open(argv[1],O_BINARY | O_RDONLY)) == -1) {
tprintf(Noread,argv[1],sys_errlist[errno]);
return -1;
}
length = filelength(handle);
if (length > 2000) {
length -= 2000;
} else {
rdsize = (int)length;
length = 0;
}
lseek(handle,length,SEEK_SET);
if(read(handle,buffer,rdsize) == -1) {
tprintf(Noread,argv[1],sys_errlist[errno]);
close(handle);
return -1;
}
for(i = rdsize - 1; i > 0; i--) {
if(buffer[i] == '\n')
line++;
if(line == Nrows - 7)
break;
}
for (; i < rdsize; i++) {
usputc(Curproc->output,buffer[i]);
}
tputs("\n");
close(handle);
return 0;
}
/* Log messages of the form
* Tue Jan 31 00:00:00 1987 44.64.0.7:1003 open FTP
*/
#if defined(ANSIPROTO)
void
log(int s,int16 protocol,char *fmt, ...)
{
FILE *Logfp;
char buf[MAXPATH];
if(Logging == FALSE)
return;
semwait(&Logwait,1);
sprintf(buf,"%s/%s.log",EtcRoot,tcp_port(protocol));
if((Logfp = Fopen(buf,APPEND_TEXT,0,0)) != NULLFILE) {
va_list ap;
struct sockaddr fsocket;
int i = SOCKSIZE;
char *cp = ctime(&currtime);
cp[24] = '\0';
fputs(cp,Logfp);
if(getpeername(s,(char *)&fsocket,&i) != -1)
fprintf(Logfp," %s",psocket(&fsocket));
fputs(" - ",Logfp);
va_start(ap,fmt);
vfprintf(Logfp,fmt,ap);
va_end(ap);
fputs("\n",Logfp);
Fclose(Logfp);
}
semrel(&Logwait);
}
#else
/*VARARGS2*/
void
log(int s,int16 protocol,char *fmt,int arg1,int arg2,int arg3,int arg4,int arg5)
{
FILE *Logfp;
char buf[MAXPATH];
if(Logging == FALSE)
return;
semwait(&Logwait,1);
sprintf(buf,"%s/%s.log",EtcRoot,tcp_port(protocol));
if((Logfp = Fopen(buf,APPEND_TEXT,0,0)) != NULLFILE) {
va_list ap;
struct sockaddr fsocket;
int i = SOCKSIZE;
char *cp = ctime(&currtime);
cp[24] = '\0';
fputs(cp,Logfp);
if(getpeername(s,(char *)&fsocket,&i) != -1)
fprintf(Logfp," %s",psocket(&fsocket));
fputs(" - ",Logfp);
fprintf(Logfp,fmt,arg1,arg2,arg3,arg4,arg5);
fputs("\n",Logfp);
Fclose(Logfp);
}
semrel(&Logwait);
}
#endif
int
dosource(int argc,char **argv,void *p)
{
FILE *fp;
/* Read command source file */
if((fp = Fopen(argv[1],READ_TEXT,0,1)) != NULLFILE) {
int linenum = 0;
char inbuf[LINELEN], intmp[LINELEN];
while(fgets(inbuf,LINELEN,fp) != NULLCHAR){
linenum++;
if(*inbuf == '#') {
continue;
}
strcpy(intmp,inbuf);
if(cmdparse(Cmds,inbuf,0) < 0) {
tprintf("ERROR - line %d:\n%s",linenum,intmp);
}
pwait(NULL);
}
Fclose(fp);
}
return 0;
}
#ifdef __TURBOC__
/*
* Fstat utility code.
* Converted to go into NOS by Kelvin Hill - G1EMM April 9, 1990
*/
extern unsigned char _osmajor;
/* Make a copy of a string pointed to by a far pointer */
static char * near
localcopy(char far *s)
{
char localstring[256], *l = localstring, far *p = s;
int i = 0;
while (*p != NULL && i++ < 255) {
*l++ = *p++;
}
*l = '\0';
return localstring;
}
/*
* Return a near pointer to a character string with the full path name of the
* program whose PSP is given in the argument. If the argument is invalid,
* this may return gibberish but I don't know how to tell Offset 0x2C in the
* PSP in the segment address of the environment of a program. Beyond the
* last environment string is a null marker, a word count (usually 1), then
* the full pathname of the owner of the environment This only works for DOS
* 3+
*/
static char * near
progname(unsigned int pid)
{
/* find the parent process psp at offset 0x16 of the psp */
unsigned ppid = *(unsigned far *) MK_FP(pid, 0x16);
/* find the environment at offset 2Ch of the psp */
unsigned far *envsegptr = (unsigned far *)MK_FP(pid, 0x2C);
char far *envptr = (char far *)MK_FP(*envsegptr, 0);
/*
* Make a pointer that contains the size of the environment block.
* Must point back one paragraph (to the environments MCB plus three
* bytes forward (to the MCB block size field).
*/
unsigned far *envsizeptr = (unsigned far *)MK_FP(*envsegptr - 1, 0x3);
unsigned envsize = *envsizeptr * 16; /* x 16 turns it into bytes */
while(envsize > 0) {
/* search for end of environment block, or NULL */
while(--envsize && *envptr++);
/*
* Now check for another NULL immediately following the first
* one located and a word count of 0001 following that.
*/
if(!*envptr && *(unsigned far *)(envptr + 1) == 0x1) {
envptr += 3;
break;
}
}
return (envsize > 0) ? localcopy(envptr) : (pid == ppid) ? "-shell-" : "unknown";
}
static int near
dofstat(void)
{
union REGS regs;
struct SREGS segregs;
char far * pfiletab, far * pnext, far * name, far * plist, far * entry;
char file[13], ownername[9], ownerext[5];
int nfiles, i, numhandles, entrylen, heading = 0;
unsigned int access, devinfo, progpsp;
long length, offset;
regs.h.ah = 0x52; /* DOS list of lists */
intdosx(®s, ®s, &segregs);
/* make a pointer to start of master list */
plist = (char far *)MK_FP(segregs.es,regs.x.bx);
/* pointer to start of file table */
pfiletab = (char far *)MK_FP(*(int far *)(plist + 6),*(int far *)(plist + 4));
switch (_osmajor) {
case 2:
entrylen = 40; /* DOS 2.x */
break;
case 3: /* DRDOS 6.0, too */
entrylen = 53; /* DOS 3.x */
break;
case 4:
case 5: /* DOS 5.0 */
case 6: /* DOS 6.0 */
entrylen = 59; /* DOS 4.x - I do not know what is in the */
break; /* extra 6 bytes */
default:
return 1;
}
for (;;) {
/* pointer to next file table */
pnext = (char far *)MK_FP(*(int far *)(pfiletab + 2),*(int far *)(pfiletab + 0));
nfiles = *(int far *)(pfiletab + 4);
#ifdef MDEBUG
tprintf("\nFile table at %Fp entries for %d files\n", pfiletab, nfiles);
#endif
for (i = 0; i < nfiles; i++) {
/* cycle through all files, quit when we reach an
* unused entry
*/
entry = pfiletab + 6 + (i * entrylen);
if (_osmajor >= 3) {
name = entry + 32;
sprintf(file,"%.11s",localcopy(name));
numhandles = *(int far *) (entry + 0);
access = (int) *(char far *) (entry + 2);
length = *(long far *) (entry + 17);
offset = *(long far *) (entry + 21);
devinfo = *(int far *) (entry + 5);
progpsp = *(int far *) (entry + 49);
} else {
name = entry + 4;
sprintf(file,"%.11s",localcopy(name));
numhandles = (int) *(char far *) (entry + 0);
access = (int) *(char far *) (entry + 1);
length = *(long far *) (entry + 19);
offset = *(long far *) (entry + 36);
devinfo = (int) *(char far *) (entry + 27);
}
if ((strlen(file) > 0) && (numhandles > 0) && !(devinfo & 0x80)) {
if(!heading) {
tputs("open files length offset hnd acc PSP device type/owner\n");
heading++; /* header now printed */
}
tprintf("%8.8s.%3.3s %8ld %8ld %2d ",file,&file[8],length,offset,numhandles);
switch (access) {
case 0:
tputs("r ");
break;
case 1:
tputs("w ");
break;
case 2:
tputs("rw");
break;
default:
tputs(" ");
}
if (_osmajor >= 3) {
tprintf(" %04X", progpsp);
} else {
tputs(" ----");
}
tprintf(" drive %c: ", 'A' + (devinfo & 0x1F));
if (devinfo & 0x8000) {
tputs("(network) ");
}
if (_osmajor >= 3) {
/*
* only DOS 3+ can find out
* the name of the program
*/
fnsplit(progname(progpsp),NULL,NULL,ownername,ownerext);
tprintf(" [%s%s]",strlwr(ownername),strlwr(ownerext));
}
tputs("\n");
}
if(strlen(file) == 0) {
return 0;
}
}
pfiletab = pnext;
}
}
#endif
int
dostatus(int argc,char **argv,void *p)
{
tprintf(version,Version,__DATE__);
tprintf("Start time: %s", ctime(&StartTime));
tprintf("System time: %s", ctime(&currtime));
tprintf("Elapsed time: %s\n\n", tformat(secclock()));
if(argc < 9) {
#ifdef MDEBUG
tprintf("Load info: CodeSeg=%04x, DataSeg=%04x\n\n", _CS, _DS);
#endif
#ifdef __TURBOC__
dofstat(); /* print status of open files */
#endif
}
return 0;
}
static void near
loadfile(void)
{
FILE *fp;
struct iface *ifp;
#ifdef NETROM
extern int donrload __ARGS((void));
extern int Nr_save;
#endif
/* loading of ip-routes */
if ((fp = Fopen(Iproutefile,READ_BINARY,0,1)) != NULLFILE) {
struct ip_saverecord ipbuf;
while(fread(&ipbuf,sizeof(struct ip_saverecord),1,fp)) {
for(ifp = Ifaces; ifp; ifp = ifp->next) {
if(ifp->niface == ipbuf.niface) {
break;
}
}
if(ifp != NULLIF) {
if (ipbuf.gateway == 0xffffffffL) {
ipbuf.gateway = 0;
}
rt_add(ipbuf.target,ipbuf.bits,ipbuf.gateway,ifp,
ipbuf.metric,0,ipbuf.flags);
}
}
Fclose(fp);
}
/* loading of arp-entries */
if ((fp = Fopen(Arproutefile,READ_BINARY,0,1)) != NULLFILE) {
struct arp_tab *p;
struct arp_saverecord arpbuf;
char hw_addr[MAXHWALEN];
if(fgetc(fp) == ARP_FILE_VERSION) { /* Version 3 required !!!! */
while(fread(&arpbuf,sizeof(struct arp_saverecord),1,fp)) {
if (fread(hw_addr, arpbuf.hwalen, 1, fp)) {
if (arpbuf.hardware < NHWTYPES) {
if ((p = arp_add(arpbuf.ip_addr,arpbuf.hardware,
hw_addr,arpbuf.pub,arpbuf.flags)) != NULLARP) {
stop_timer(&p->timer);
set_timer(&p->timer,0L);
}
}
}
}
}
Fclose(fp);
}
#ifdef AX25
/* loading of ax25-routes */
if ((fp = Fopen(Axroutefile,READ_BINARY,0,1)) != NULLFILE) {
struct axroute_tab *rp;
struct ax_saverecord axbuf;
struct iface *ifptable[ASY_MAX
#ifdef SCC
+ MAXSCC
#endif
#ifdef VANESSA
+ VAN_MAX
#endif
#ifdef AXIP
+ NAX25
#endif
];
memset(ifptable,0,sizeof(ifptable));
for (ifp = Ifaces; ifp; ifp = ifp->next) {
if (ifp->output == ax_output) {
ifptable[ifp->niface] = ifp;
}
}
while (fread(&axbuf,sizeof(struct ax_saverecord),1,fp)) {
if (axbuf.time + Axholdtime < currtime) {
continue;
}
rp = axroute_tabptr(&axbuf.call, 1);
if (axbuf.digi.call[0]) {
rp->digi = axroute_tabptr(&axbuf.digi, 1);
}
if (axbuf.dev >= 0 && axbuf.dev < Niface) {
rp->ifp = ifptable[axbuf.dev];
}
rp->time = axbuf.time;
}
Fclose(fp);
}
#endif
#ifdef NETROM
if(Nr_save) donrload();
#endif
}
int
dosavefile(int argc,char **argv,void *p)
{
FILE *fp;
#ifdef NETROM
extern int donrsave __ARGS((void));
extern int Nr_save;
#endif
if(uploadstatus) {
return 0;
}
if((fp = Fopen(Iproutefile,WRITE_BINARY,0,1)) != NULLFILE) {
struct ip_saverecord buf;
struct route *rp;
for(rp = Routes; rp != NULLROUTE; rp = rp->next) {
if(rp->target == 0 || rp->flags >= RTPRIVATE || run_timer(&rp->timer)) {
continue;
}
buf.target = rp->target;
buf.bits = rp->bits;
buf.gateway = (rp->gateway != 0) ? rp->gateway : 0xffffffffL;
buf.niface = rp->iface->niface;
buf.metric = rp->metric;
buf.flags = rp->flags;
fwrite(&buf,sizeof(struct ip_saverecord),1,fp);
}
Fclose(fp);
}
pwait(NULL);
if((fp = Fopen(Arproutefile,WRITE_BINARY,0,1)) != NULLFILE) {
struct arp_saverecord buf;
struct arp_tab *p;
fputc(ARP_FILE_VERSION, fp);
for (p = Arp_tab; p; p = p->next) {
if (p->hw_addr && p->state == ARP_VALID) {
buf.ip_addr = p->ip_addr;
buf.hardware = p->hardware;
buf.flags = p->flags;
buf.hwalen = p->hwalen;
buf.pub = p->pub;
fwrite(&buf,sizeof(struct arp_saverecord),1,fp);
fwrite(p->hw_addr, p->hwalen, 1, fp);
}
}
Fclose(fp);
}
pwait(NULL);
#ifdef AX25
if((fp = Fopen(Axroutefile,WRITE_BINARY,0,1)) != NULLFILE) {
struct ax_saverecord buf;
struct axroute_tab *rp, *lp;
for (lp = 0, rp = Axroute_tab; rp; ) {
if (rp->time + Axholdtime >= currtime) {
buf.call = rp->call;
if (rp->digi) {
buf.digi = rp->digi->call;
} else {
buf.digi.call[0] = '\0';
}
buf.dev = rp->ifp ? rp->ifp->niface : -1;
buf.time = rp->time;
fwrite(&buf,sizeof(struct ax_saverecord),1,fp);
lp = rp;
rp = rp->next;
} else if (lp) {
lp->next = rp->next;
xfree(rp);
rp = lp->next;
} else {
Axroute_tab = rp->next;
xfree(rp);
rp = Axroute_tab;
}
}
Fclose(fp);
}
pwait(NULL);
#endif
#ifdef NETROM
if(Nr_save) donrsave();
#endif
return 0;
}
int
doattribute(int argc,char **argv,void *p)
{
if(*argv[1] == 'm') {
normal = 112;
normalh = 15;
normals = 112;
invers = 240;
red = 127;
common = 7;
panic = 143;
} else {
normal = NORMALL;
normalh = NORMALH;
normals = NORMALS;
invers = INVERS;
red = RED;
common = COMMON;
panic = PANIC;
}
return 0;
}
#ifdef RESETTIMER
static void near
inittim(void)
{
outport(TIMCTRL,0x36); /*Init Timer0 for sqarewavegeneration*/
outport(TIMER0,0x50);
outport(TIMER0,0x50); /*Teilerfaktor für Timer0 0xffff*/
outport(TIMCTRL,0x78); /*Init Timer1 for squarewavegeneration*/
outport(TIMER1,0xff);
outport(TIMER1,0x0d);
outport(TIMCTRL,0xb4); /*Init Timer2 for sqarewavegeneration*/
outport(TIMER2,0xff);
outport(TIMER2,0x20);
outport(IOCTRL,0x80); /*Set all I/O-Ports to output im Mode0*/
outport(IOCTRL,0x80);
outport(PORTC,0xff); /*activate Reset*/
return;
}
#endif
static void near
cprint_timer(struct timer *timer)
{
switch(timer->state) {
case TIMER_RUN:
cprintf("%3lu",read_timer(timer)/1000);
break;
case TIMER_STOP:
cputs(" -");
break;
case TIMER_EXPIRE:
cputs(" E");
break;
}
cprintf("/%3lu│",dur_timer(timer)/1000);
}
static void
dostatustimer(void)
{
if(!istate()) { /* return if in critical section */
start_timer(&Statustimer);
return;
}
alert(statp,(void *)1); /* wake process */
}
void
statusline(int i,void *v1, void *v2)
{
struct text_info str;
struct time sttime;
struct session *sp;
struct usock *up;
int s, flag;
char size;
extern int Attended;
static unsigned min = 100;
time(&currtime);
statp = Curproc;
Statustimer.func = (void (*)())dostatustimer; /* what to call on timeout*/
Statustimer.arg = NULLCHAR; /* dummy value */
set_timer(&Statustimer,990); /* set timer duration, appr. 1 sec*/
#ifdef MDEBUG
strcpy(Statustimer.tname,"Status");
#endif
start_timer(&Statustimer);
for(; ;) {
pwait(&sttime);
stop_timer(&Statustimer);
/*-----------------------------------------------------------*
* get the current time *
* well, I don't think, one minute is a long time. between *
* minutes, the accuracy of the time is given by the NOS *
* timers. Every minute the various variables are synced *
* with the system time. *
*-----------------------------------------------------------*/
gettime(&sttime);
currtime++; /* increment system wide time_t */
if(sttime.ti_min != min) {
time(&currtime); /* resync system time */
min = sttime.ti_min;
EMinute = min + sttime.ti_hour * 60;
if(Eproc && EVwait == 0) {
alert(Eproc,(void *)EMinute); /* wake event process */
}
}
#ifdef RESETTIMER
outport(TIMER1,0xff); /* Reset Timer */
outport(TIMER1,0x0d);
#endif
gettextinfo(&str);
window(1,1,80,2);
gotoxy(1,1);
if((size = !availmem()) != 0) {
textattr(panic);
cputs(" PANIC ");
} else {
textattr(red);
cputs(" WNOS5 ");
textattr(normal);
}
if(Current->type == COMMAND || Current->type == TRACESESSION || size) {
cprintf(" Coreleft%7lu",coreleft());
} else {
cprintf(" %-15.15s",Current->name);
}
s = -1;
cprintf("│%-8s",(Current->type == FTP
&& (s = Current->cb.ftp->data) != -1)
? "FTP-DATA" : Sestypes[Current->type]);
if((up = itop((s == -1) ? Current->s : s)) != NULLUSOCK) {
switch(up->type) {
default:
case TYPE_RAW: /* fix to bad status line */
goto line; /* in ping session */
case TYPE_TCP: {
struct tcb *tcb = up->cb.tcb;
if(tcb != NULLTCB) {
if(s == -1) {
cprintf("│Backoff%3u│TxQ%7u│RTT ",
tcb->backoff,tcb->sndcnt);
} else {
cprintf("│Rx%8lu│Tx%8lu│RTT ",
tcb->rcv.nxt - tcb->irs,tcb->snd.una - tcb->iss);
}
cprint_timer(&tcb->timer);
cputs(" ");
} else {
goto line;
}
break;
}
#ifdef AX25
case TYPE_AX25I: {
struct ax25_cb *axp = up->cb.ax25;
if(axp != NULLAX25) {
cprintf("│Retries%3d│Unack%5d│",axp->retries,axp->unack);
if(axp->dama) {
cprintf("DAMA-Tx%4d│",len_p(axp->txq));
} else {
cputs("T1 ");
cprint_timer(&axp->t1);
}
cputs(axp->remotebusy ? "RNR" : " ");
} else {
goto line;
}
break;
}
#endif
#ifdef NETROM
case TYPE_NETROML4: {
struct nr4_cb *nr4 = up->cb.nr4;
if(nr4 != NULLNR4CB) {
cprintf("│Retries%3d│Unack%5d│SRTT%7ld│%s",
nr4->txmax,nr4->nbuffered,
nr4->srtt,nr4->choked ? "CHK" : " ");
} else {
goto line;
}
break;
}
#endif
}
} else {
line:
cprintf("%31sttended",Attended ? " A" : "Una");
}
if((flag = sttime.ti_sec & 1) != 0 && Current->rfile != NULLCHAR) {
cputs("│R");
} else if(!flag && Current->ufile != NULLCHAR) {
cputs("│U");
} else {
cputs("│ ");
}
cprintf("│ %02d%c%02d ",sttime.ti_hour,flag ? ' ' : ':',sttime.ti_min);
/* 2nd line starts here */
textattr(normals);
for(sp = Sessions, s = 0; sp < &Sessions[Nsessions]; sp++) {
if(sp->type == COMMAND || sp->type == TRACESESSION) {
continue;
}
s++;
if(sp->type != FREE) {
if(socklen(sp->output,1)) {
textattr(invers);
}
cprintf(" %d:%s%s%s ",
s,
(sp->rfile == NULLCHAR) ? "" : "R:",
(sp->ufile == NULLCHAR) ? "" : "U:",
sp->name);
textattr(normals);
}
}
clreol();
window(str.winleft,str.wintop,str.winright,str.winbottom);
textattr(common);
gotoxy(str.curx,str.cury);
start_timer(&Statustimer);
}
}